package project.web.processor;

import java.util.Objects;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import online.model.session.SessionUser;
import online.struts.action.UniForm;
import online.struts.chain.command.ActionRequest;
import online.struts.mapping.RequestMapping;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.struts.action.ActionForm;
import org.apache.struts.chain.commands.ActionCommandBase;
import org.apache.struts.chain.contexts.ActionContext;
import org.apache.struts.chain.contexts.ServletActionContext;
import org.apache.struts.config.ActionConfig;

/**
 * 操作ログ出力プロセッサ
 *
 * @author Tadashi Nakayama
 * @version 1.0.0
 */
public final class RequestLogProcessor extends ActionCommandBase {
	/** ログ出力クラス */
	private static final Logger LOGGER = LogManager.getLogger(RequestLogProcessor.class);

	/** タグ ユーザID */
	private static final String TAG_UID = "UID";
	/** セパレータ */
	private static final String SEPARATOR = "\t";

	/**
	 * @see org.apache.struts.chain.commands.ActionCommandBase
	 * #execute(org.apache.struts.chain.contexts.ActionContext)
	 */
	@Override
	public boolean execute(final ActionContext context) throws Exception {

		if (ServletActionContext.class.isInstance(context)) {
			ServletActionContext sac = ServletActionContext.class.cast(context);

			if (ActionRequest.isFirst(sac, this.getClass())) {
				ActionForm af = sac.getActionForm();
				if (UniForm.class.isInstance(af)) {
					// 開始ログ
					requestLog(sac, UniForm.class.cast(af));
				}
			}
		}

		return false;
	}

	/**
	 * 開始ログ出力処理
	 *
	 * @param sac ServletActionContext
	 * @param form アクションフォーム
	 */
	private void requestLog(final ServletActionContext sac, final UniForm form) {
		StringBuilder sb = getHeaderInfo(sac, form);
		sb.append(SEPARATOR);
		// ログ出力区分
		sb.append("type:Request");

		LOGGER.fatal(sb.toString());
	}

	/**
	 * ヘッダ情報（アクションIDまで）取得
	 *
	 * @param sac ServletActionContext
	 * @param uf 汎用フォーム
	 * @return ヘッダ情報
	 */
	private StringBuilder getHeaderInfo(final ServletActionContext sac, final UniForm uf) {
		StringBuilder sb = new StringBuilder();
		// セションID
		sb.append("sid:");
		sb.append(getSessionId(sac));
		sb.append(SEPARATOR);
		// ユーザID
		sb.append("ident:");
		sb.append(getUid(sac.getRequest(), uf));
		sb.append(SEPARATOR);
		// IPアドレス
		sb.append("host:");
		sb.append(Objects.toString(uf.getActionParameter().getIp(), ""));
		sb.append(SEPARATOR);
		// 機能ID
		sb.append("fid:");
		sb.append(Objects.toString(getGid(sac.getActionConfig()), ""));
		sb.append(SEPARATOR);
		// アクションID
		sb.append("aid:");
		sb.append(Objects.toString(getAid(uf), ""));
		return sb;
	}

	/**
	 * セションID取得
	 * @param sac ServletActionContext
	 * @return セションID
	 */
	private String getSessionId(final ServletActionContext sac) {
		HttpSession session = sac.getRequest().getSession(false);
		if (session != null) {
			return session.getId();
		}
		return "";
	}

	/**
	 * ユーザID取得
	 *
	 * @param uf 汎用フォーム
	 * @param request HttpServletRequest
	 * @return ユーザID
	 */
	public static String getUid(final HttpServletRequest request, final UniForm uf) {
		String ret = null;
		SessionUser su = uf.getSessionUser();
		if (su != null) {
			ret = su.getUid();
		}
		if (Objects.toString(ret, "").trim().isEmpty()) {
			ret = uf.getString(TAG_UID);
		}
		if (Objects.toString(ret, "").trim().isEmpty()) {
			ret = request.getRemoteUser();
		}
		return ret;
	}

	/**
	 * 画面ID取得
	 *
	 * @param ac アクションコンフィグ
	 * @return 画面ID
	 */
	public static String getGid(final ActionConfig ac) {
		if (RequestMapping.class.isInstance(ac)) {
			return RequestMapping.class.cast(ac).getGid();
		}
		return null;
	}

	/**
	 * アクションID取得
	 *
	 * @param uf 汎用フォーム
	 * @return アクションID
	 */
	public static String getAid(final UniForm uf) {
		String ret = uf.getActionParameter().getAid();
		if (Objects.toString(ret, "").trim().isEmpty()) {
			ret = uf.getString("AID");
		}
		return ret;
	}
}
